﻿#pragma once

#include <functional>
#include <map>
#include <string>
#include <mutex>
#include "ffmpeg_headers.h"
#include "../3rdparty/json/json.h"
typedef std::function<void(uint8_t* y, int strideY, uint8_t* u, int strideU, uint8_t* v, int strideV, int nWidth, int nHeight, int64_t nTimeStamp)> VideoYuvCallBack;

typedef std::function<void(char* h264_raw, int file_size, bool bKey, int nWidth, int nHeight, int fps, int64_t nTimeStamp)> H264CallBack;


enum PlayEvenID {
	MEDIA_NONE = 0, //ÎÞ²¥·Å
	MEDIA_START = 1, //¿ªÊŒ 
	MEDIA_PLAY = 2, //²¥·ÅÖÐ 
	MEDIA_PAUSE = 3,//ÔÝÍ£
	MEDIA_STOP = 4, //²¥·ÅÍ£Ö¹
	MEDIA_END = 5, //²¥·ÅœáÊø
	MEDIA_ERROR = 6  //²¥·ÅÒì³£
};


#if defined(WEBRTC_WIN) || defined(WEBRTC_LINUX)
#include "api/video/video_frame.h"
typedef std::function<void(const webrtc::VideoFrame& videoFrame)> FrameCallBack;
#endif // WEBRTC_WIN


/*
	std::map<std::string, std::string> opts;
	opts["width"] = to_string(m_StreamConfig.nWidth);
	opts["height"] = to_string(m_StreamConfig.nHeight);
	opts["fps"] = to_string(m_StreamConfig.fps);
	opts["bitrate"] = to_string(m_StreamConfig.startVideoBitrate);
	opts["timeout"] = to_string(5);
if (opts.find("width") != opts.end()) {
	width = std::stoi(opts.at("width"));
}
if (opts.find("height") != opts.end()) {
	height = std::stoi(opts.at("height"));
}
if (opts.find("fps") != opts.end()) {
	fps = std::stoi(opts.at("fps"));
}

*/

class  VideoCapture
{
public:
	static VideoCapture* CreateVideoCapture(std::string videourl = "");

	VideoCapture()
	{
	}
	virtual  ~VideoCapture()
	{
	}
	virtual bool Start() = 0;

	virtual void Init(const char* devicename, int nWidth, int nHeight, int nFrameRate = 30) = 0;

	virtual void Initdectect(const char* strJson) = 0;

	virtual void Stop(VideoYuvCallBack yuvCallback) = 0;

	virtual void Destroy() = 0;

	virtual void RegisterCallback(VideoYuvCallBack yuvCallback) = 0;

	virtual void RegisterH264Callback(H264CallBack yuvCallback) = 0;

	virtual bool onData(const char* id, unsigned char* buffer, int size, int64_t ts) = 0;

	virtual bool onData(uint8_t* y, int strideY, uint8_t* u, int strideU, uint8_t* v, int strideV, int nWidth, int nHeight, int64_t nTimeStamp) = 0;

	virtual bool isDectect() = 0;

	virtual const Json::Value detectorinfo(const Json::Value& jmessage) = 0;

	virtual void stopDetector() = 0;

	virtual bool isPlay() = 0;

	virtual void setCallbackEvent(MediaSourceEvent* callbackevent) = 0;
};




class  VideoCaptureManager
{
public:
	// ÌíŒÓÊäÈëÁ÷
	VideoCapture* AddInput(const std::string& videoUrl);

	// ÒÆ³ýÊäÈëÁ÷
	void RemoveInput(const std::string videoUrl);

	// »ñÈ¡ÊäÈëÁ÷¶ÔÏó
	VideoCapture* GetInput(const std::string& videoUrl);

	std::string  getStream(const std::string& videoUrl);

	bool isURLWithProtocol(const std::string& str) {
		// ÅÐ¶Ï×Ö·ûŽ®ÊÇ·ñÒÔÐ­Òé¿ªÍ·£¬±ÈÈç "rtsp://"
		return (str.substr(0, 7) == "rtsp://" || str.substr(0, 7) == "http://" || str.substr(0, 7) == "rtmp://");
	}

	std::string extractPathFromURL(const std::string& url) {
		size_t pos = url.find("://");
		if (pos != std::string::npos) {
			// Èç¹û×Ö·ûŽ®°üº¬Ð­Òé£¬ÌáÈ¡Ð­ÒéºóµÄÂ·Ÿ¶²¿·Ö
			return url.substr(pos + 3);
		}
		else {
			// Èç¹ûÃ»ÓÐÐ­Òé£¬Ö±œÓ·µ»ØÔ­ÊŒ×Ö·ûŽ®
			return url;
		}
	}

	std::string getPortionAfterPort(const std::string& str) {
		size_t startPos = str.find(':', 6); // ŽÓµÚ6žö×Ö·û¿ªÊŒ²éÕÒÃ°ºÅ£¬Ìø¹ýÐ­Òé²¿·Ö
		if (startPos == std::string::npos) {
			return ""; // ÕÒ²»µœÃ°ºÅ£¬·µ»Ø¿Õ×Ö·ûŽ®
		}

		size_t endPos = str.find('/', startPos); // ŽÓÃ°ºÅºóÃæ²éÕÒµÚÒ»žöÐ±žÜ
		if (endPos == std::string::npos) {
			return ""; // ÕÒ²»µœÐ±žÜ£¬·µ»Ø¿Õ×Ö·ûŽ®
		}

		return str.substr(endPos); // ÌáÈ¡Ð±žÜºóÃæµÄ²¿·Ö
	}

public:
	static VideoCaptureManager& getInstance();
private:
	VideoCaptureManager() = default;
	~VideoCaptureManager() {};
	VideoCaptureManager(const VideoCaptureManager&) = delete;
	VideoCaptureManager& operator=(const VideoCaptureManager&) = delete;

private:
	std::mutex m_mutex;
	std::map<std::string, VideoCapture*> m_inputMap;
public:
};
